home *** CD-ROM | disk | FTP | other *** search
/ Super Shareware Collection / Super Shareware Collection.iso / os_2 / pm22x333.zip / PMODE.ASM < prev    next >
Assembly Source File  |  1994-02-21  |  74KB  |  2,182 lines

  1. ; PMODE v2.2x333 raw, DPMI, VCPI, & XMS compliant protected mode header.
  2. ; By Tran (a.k.a. Thomas Pytel).
  3.  
  4.         .386p
  5.  
  6. LOWMIN          = 0             ; minimum free low memory (in K)
  7. EXTMIN          = 0             ; minimum free extended memory (in K)
  8. STAKLEN         = 200h          ; stack size in para (keep below or = 1000h)
  9. STAKSAFE        = 30h           ; safe stack space in para
  10. SELECTORS       = 1             ; extra selectors for allocation
  11.  
  12. code16  segment para public use16
  13. code16  ends
  14. code32  segment para public use32
  15. code32  ends
  16. codeend segment para stack use32 'stack'
  17. codeend ends
  18.  
  19. ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  20. ; Real mode and 16bit code
  21. ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  22. code16  segment para public use16
  23.         assume cs:code16, ds:code16
  24.         org 0
  25.  
  26. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  27. ; 16 bit common system data
  28. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  29. errmsg0         db      '386 or better not detected!!!',7,'$'
  30. errmsg1         db      'Not enough low memory!!!',7,'$'
  31. errmsg2         db      'System is already in V86 mode, and no VCPI or DPMI found!!!',7,'$'
  32. errmsg3         db      'Not enough extended memory!!!',7,'$'
  33. errmsg4         db      'Couldn''t enable A20 gate!!!',7,'$'
  34. errmsg5         db      'Extended memory allocation failure. (weird eh???)',7,'$'
  35.  
  36. nullint         db      0cfh            ; IRET instruction
  37. exitrout        dw      exit            ; exit routine, modified if XMS, VCPI
  38.  
  39. savedstakoff    dw      ?               ; current saved stack offset
  40. savedstakseg    dw      ?               ; current saved stack segment
  41.  
  42. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  43. ; 16 bit common system code
  44. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  45. ;═════════════════════════════════════════════════════════════════════════════
  46. intreal:                                ; real mode int, load FS and GS here
  47.         pushf
  48. ;-----------------------------------------------------------------------------
  49. callreal:                               ; real mode call, load FS and GS here
  50.         push cs
  51.         push offset icreald
  52.         mov fs,cs:v86r_fs
  53.         mov gs,cs:v86r_gs
  54.         mov eax,cs:v86r_eax
  55.         mov ecx,cs:v86r_ecx
  56.         mov edx,cs:v86r_edx
  57.         mov ebx,cs:v86r_ebx
  58.         mov esi,cs:v86r_esi
  59.         mov edi,cs:v86r_edi
  60.         mov ebp,cs:v86r_ebp
  61. ;-----------------------------------------------------------------------------
  62. icreal:                                 ; real mode int, call, or IRQ
  63.         db 66h,68h              ; PUSH destination addx
  64. icrealm1        dd      ?       ;
  65. icrealm0        db      ?       ; CLI or STI
  66.         retf
  67. ;-----------------------------------------------------------------------------
  68. icreald:                                ; done with real int or call
  69.         cli
  70.         pushf
  71.         pop cs:v86r_flags
  72.         mov cs:v86r_eax,eax
  73.         mov cs:v86r_ecx,ecx
  74.         mov cs:v86r_edx,edx
  75.         mov cs:v86r_ebx,ebx
  76.         mov cs:v86r_esi,esi
  77.         mov cs:v86r_edi,edi
  78.         mov cs:v86r_ebp,ebp
  79.         mov cs:v86r_ds,ds
  80.         mov cs:v86r_es,es
  81.         mov cs:v86r_fs,fs
  82.         mov cs:v86r_gs,gs
  83. icreald2:
  84.         mov ax,cs
  85.         mov ds,ax
  86. icrealm2        label word              ; return to pmode modifiable to JMP
  87. ;-----------------------------------------------------------------------------
  88.         mov ebx,ds:cp_savedstakoff      ; DPMI return to pmode
  89.         mov dx,ds:dp_savedstaksel
  90.         mov edi,offset dp_int3_d
  91.         mov si,ds:_selcode
  92.         mov cx,dx
  93.         mov ax,ds:_seldata
  94.         jmp ds:d_switchaddx
  95. ;-----------------------------------------------------------------------------
  96. VICREAL1D=(($-(icrealm2+2))shl 8)+0ebh
  97. v_icreal1d:                             ; VCPI return to pmode from safe
  98.         mov edi,offset cp_int3_d
  99. ;-----------------------------------------------------------------------------
  100. ; EDI=offset to jump to in code32
  101. v_switchtopmode:                        ; VCPI switch to pmode
  102.         mov ds:v_ss_dest,edi
  103.         mov esi,offset v_ss_cr3
  104.         add esi,ds:_code16a
  105.         mov ax,0de0ch
  106.         int 67h
  107. ;-----------------------------------------------------------------------------
  108. CICREAL1D=(($-(icrealm2+2))shl 8)+0ebh
  109. c_icreal1d:                             ; custom return to pmode from safe
  110.     mov edi,offset cp_int3_d
  111. ;-----------------------------------------------------------------------------
  112. ; EDI=offset in pmode to jump to
  113. c_retpmode:                             ; reenter 32bit pmode
  114.         lgdt fword ptr c_gdt32addx      ; set up pmode GDT and IDT
  115.     lidt fword ptr c_idt32addx
  116.     mov ds:gdt32task[5],89h     ; set task as not busy
  117.         mov eax,cr0                     ; switch to pmode
  118.         or al,1
  119.         mov cr0,eax
  120.         db 0eah
  121.         dw $+4,20h
  122.         mov ax,30h                      ; load task register
  123.         ltr ax
  124.     jmp c_gotopmode
  125. ;-----------------------------------------------------------------------------
  126. if ($-(icrealm2+2)) gt 127
  127.   err
  128. endif
  129. CICREAL0D=(($-(icrealm2+2))shl 8)+0ebh
  130. c_icreal0d:                             ; return to pmode from normal
  131.         int 0ffh
  132. ;═════════════════════════════════════════════════════════════════════════════
  133. int32:                                  ; real mode INT32: EDX=off
  134.         pushad
  135.         push ds es fs gs
  136.         cli
  137.         mov ax,cs
  138.         mov ds,ax
  139.         mov ds:p_cpmodem0,edx
  140.         mov al,[esp+45]
  141.         shr al,1
  142.         and al,1
  143.         add al,0fah
  144.         mov ds:p_cpmodem1,al
  145.         push savedstakoff
  146.         push savedstakseg
  147.         movzx ebx,ds:nextmodestack
  148.         lea eax,[ebx-STAKSAFE*16]
  149.         mov ds:nextmodestack,ax
  150.         add ebx,ds:realstackbase
  151.         mov savedstakseg,ss
  152. int32m0         label   word            ; jump to pmode, modifiable
  153. ;-----------------------------------------------------------------------------
  154.         sub sp,ds:dp_savelen
  155.         mov savedstakoff,sp
  156.         mov ax,ss                       ; DPMI jump to pmode
  157.         mov es,ax
  158.         mov di,sp
  159.         xor al,al
  160.         call d_saveaddx
  161.         mov ax,ds:_seldata
  162.         mov cx,ax
  163.         mov dx,ax
  164.         mov edi,offset p_cpmode
  165.         mov si,ds:_selcode
  166.         jmp ds:d_switchaddx
  167. ;-----------------------------------------------------------------------------
  168. VINT32=(($-(int32m0+2))shl 8)+0ebh
  169. v_int32:                                ; VCPI call pmode
  170.         push ds:p_cpmodem2
  171.         mov ds:p_cpmodem2,VCPMODED
  172.         mov savedstakoff,sp
  173.         mov edi,offset p_cpmode1
  174.         jmp v_switchtopmode
  175. ;-----------------------------------------------------------------------------
  176. if ($-(int32m0+2)) gt 127
  177.   err
  178. endif
  179. CINT32=(($-(int32m0+2))shl 8)+0ebh
  180. c_int32:                                ; raw/XMS call pmode
  181.         push ds:p_cpmodem2
  182.         mov ds:p_cpmodem2,CCPMODED
  183.         mov savedstakoff,sp
  184.         mov edi,offset p_cpmode1
  185.         jmp c_retpmode
  186. ;═════════════════════════════════════════════════════════════════════════════
  187. int32d0:                                ; DPMI done with pmode call
  188.         mov di,sp
  189.         mov al,1
  190.         call d_saveaddx
  191.         add sp,ds:dp_savelen
  192. ;-----------------------------------------------------------------------------
  193. int32d2:                                ; done from all
  194.         pop savedstakseg
  195.         pop savedstakoff
  196.         add ds:nextmodestack,STAKSAFE*16
  197.         mov bx,ds:v86r_flags
  198.         mov ax,[esp+44]
  199.         and ax,not 8d5h
  200.         and bx,8d5h
  201.         or ax,bx
  202.         mov [esp+44],ax
  203.         pop gs fs es ds
  204.         popad
  205.         iret
  206. ;═════════════════════════════════════════════════════════════════════════════
  207. int32d1:                                ; VCPI done with pmode call
  208.         mov ss,savedstakseg
  209.         pop ds:p_cpmodem2
  210.         jmp int32d2
  211. ;═════════════════════════════════════════════════════════════════════════════
  212. int32d3:                                ; raw/XMS done with pmode call
  213.         mov c_retreal0m0,offset c_sicreal
  214.         mov ax,cs
  215.         mov ds,ax
  216.         movzx esp,savedstakoff
  217.         mov ss,savedstakseg
  218.         pop ds:p_cpmodem2
  219.         jmp int32d2
  220. ;─────────────────────────────────────────────────────────────────────────────
  221. chek_VCPI:                              ; Chek for VCPI
  222.         xor ax,ax
  223.         mov gs,ax
  224.         mov ax,gs:[67h*4]
  225.         or ax,gs:[(67h*4)+2]
  226.         jz short chekVCPIa
  227.         mov ax,0de00h
  228.         int 67h
  229.         or ah,ah
  230.         clc
  231.         jz short chekVCPId
  232. chekVCPIa:
  233.         stc
  234. chekVCPId:
  235.         ret
  236. ;─────────────────────────────────────────────────────────────────────────────
  237. chek_processor:                         ; Detect if current processor 386
  238.         pushf
  239.         xor ah,ah
  240.         push ax
  241.         popf
  242.         pushf
  243.         pop ax
  244.         and ah,0f0h
  245.         cmp ah,0f0h
  246.         je short detectno386
  247.         mov ah,0f0h
  248.         push ax
  249.         popf
  250.         pushf
  251.         pop ax
  252.         and ah,0f0h
  253.         jz short detectno386
  254.         popf
  255.         ret
  256. detectno386:
  257.         mov dx,offset errmsg0
  258.         jmp short exit16err
  259. ;─────────────────────────────────────────────────────────────────────────────
  260. chek_V86:                               ; Chek if already in V86 mode
  261.         smsw ax
  262.         test al,1
  263.         mov dx,offset errmsg2
  264.         jnz short exit16err
  265.         ret
  266. ;─────────────────────────────────────────────────────────────────────────────
  267. pregetlomem:                            ; Get low memory or abort
  268.         add eax,ds:_lomembase
  269.         mov ebx,ds:_lomemtop
  270.         cmp eax,ebx
  271.         ja short pregetlomema
  272.         mov ecx,eax
  273.         xchg eax,ds:_lomembase
  274.         sub ebx,ecx
  275.         cmp ebx,LOWMIN*1024
  276.         jb short pregetlomema
  277.         ret
  278. pregetlomema:
  279.         mov dx,offset errmsg1
  280. ;─────────────────────────────────────────────────────────────────────────────
  281. exit16err:                              ; Exit program with message
  282.         mov ah,9
  283.         int 21h
  284.         jmp exitrout
  285. ;-----------------------------------------------------------------------------
  286. exit:                                   ; Guess what???
  287.         mov ah,4ch
  288.         int 21h
  289. ;═════════════════════════════════════════════════════════════════════════════
  290. start16:                                ; Program begins here
  291.         cli
  292.         cld
  293.         push cs
  294.         pop ds
  295.  
  296.         call chek_processor             ; is it at least a 386¿
  297.  
  298.         mov ax,es                       ; set up a bunch of pointers
  299.         movzx eax,ax
  300.         shl eax,4
  301.         mov ds:_pspa,eax
  302.         mov eax,code16
  303.         shl eax,4
  304.         mov ds:_code16a,eax
  305.         or dword ptr ds:gdt32code16[2],eax
  306.         or dword ptr ds:gdt32data16[2],eax
  307.         mov ebx,code32
  308.         shl ebx,4
  309.         mov ds:_code32a,ebx
  310.         or dword ptr ds:gdt32code32[2],ebx
  311.         or dword ptr ds:gdt32data32[2],ebx
  312.         add dword ptr ds:c_gdt32addx[2],ebx
  313.         mov eax,codeend
  314.         shl eax,4
  315.         sub eax,ebx
  316.         mov ds:_lomembase,eax
  317.         mov ds:realstackbase,eax
  318.         movzx eax,word ptr es:[2]
  319.         shl eax,4
  320.         sub eax,ebx
  321.         mov ds:_lomemtop,eax
  322.  
  323.         mov eax,STAKLEN*16              ; get stack memory
  324.         call pregetlomem
  325.  
  326.         push es                         ; save PSP seg (DPMI chek kills ES)
  327.         pop fs
  328.  
  329.         mov ax,1687h                    ; chek for DPMI
  330.         int 2fh
  331.         or ax,ax
  332.         jz d_start
  333.  
  334.         call chek_VCPI                  ; chek for VCPI
  335.         jnc v_start
  336.  
  337.         call chek_V86                   ; chek for V86 mode
  338.  
  339.         mov ax,4300h                    ; chek for XMS
  340.         int 2fh
  341.         cmp al,80h
  342.         je x_start
  343.  
  344.         jmp c_start                     ; custom system start
  345. ;─────────────────────────────────────────────────────────────────────────────
  346. enableA20:                              ; hardware enable gate A20
  347.         xor ax,ax
  348.         mov fs,ax
  349.         dec ax
  350.         mov gs,ax
  351.         call testA20
  352.         je short enableA20done
  353.         in al,92h                       ; PS/2 A20 enable
  354.         or al,2
  355.         jmp short $+2
  356.         jmp short $+2
  357.         jmp short $+2
  358.         out 92h,al
  359.         call testA20
  360.         je short enableA20done
  361.         call enableA20o1                ; AT A20 enable
  362.         jnz short enableA20wait
  363.         mov al,0d1h
  364.         out 64h,al
  365.         call enableA20o1
  366.         jnz short enableA20wait
  367.         mov al,0dfh
  368.         out 60h,al
  369.         push offset enableA20wait
  370. enableA20o1:
  371.         mov ecx,20000h
  372. enableA20o1l:
  373.         jmp short $+2
  374.         jmp short $+2
  375.         jmp short $+2
  376.         in al,64h
  377.         test al,2
  378.         loopnz enableA20o1l
  379. enableA20done:
  380.         ret
  381. ;-----------------------------------------------------------------------------
  382. enableA20wait:                          ; wait for A20
  383.         mov al,36h
  384.         out 43h,al
  385.         xor al,al
  386.         out 40h,al
  387.         out 40h,al
  388.         mov cx,800h
  389. enableA20waitl0:
  390.         call testA20
  391.         je enableA20done
  392.         in al,40h
  393.         in al,40h
  394.         mov ah,al
  395. enableA20waitl1:
  396.         in al,40h
  397.         in al,40h
  398.         cmp al,ah
  399.         je enableA20waitl1
  400.         loop enableA20waitl0
  401.         mov dx,offset errmsg4
  402.         jmp exit16err
  403. ;-----------------------------------------------------------------------------
  404. testA20:                                ; Test for enabled A20
  405.         mov al,fs:[0]
  406.         mov ah,al
  407.         not al
  408.         mov gs:[10h],al
  409.         cmp ah,fs:[0]
  410.         mov fs:[0],ah
  411.         ret
  412. ;─────────────────────────────────────────────────────────────────────────────
  413. ; BL=low PIC val, BH=high PIC val
  414. setintslots:                            ; set int nums in table to PIC vals
  415.         mov edi,offset ds:intslottbl
  416.         mov cl,8
  417. setintslotsl0:
  418.         mov [di],bl
  419.         inc di
  420.         inc bl
  421.         dec cl
  422.         jnz setintslotsl0
  423.         mov cl,8
  424. setintslotsl1:
  425.         mov [di],bh
  426.         inc di
  427.         inc bh
  428.         dec cl
  429.         jnz setintslotsl1
  430.         ret
  431.  
  432. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  433. ; 16 bit DPMI system data
  434. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  435. d_errmsg0       db      'DPMI host is not 32bit!!!',7,'$'
  436. d_errmsg1       db      'Ran out of DPMI descriptors!!!',7,'$'
  437. d_errmsg2       db      'Couldn''t set DPMI descriptors as needed!!!',7,'$'
  438.  
  439. d_enterpmode    dw      ?,?             ; DPMI switch to pmode addx
  440. d_pspsel        dw      ?               ; stupid PSP selector
  441. d_oldenvsegsel  dw      ?               ; stupid selector we dont want
  442.  
  443. d_switchaddx    dd      ?               ; switch to pmode addx
  444. d_saveaddx      dd      ?               ; save/restore state addx
  445.  
  446. d_nintoff       dd      offset dp_irq0,offset dp_irq1,offset dp_irq2,offset dp_irq3
  447.                 dd      offset dp_irq4,offset dp_irq5,offset dp_irq6,offset dp_irq7
  448.                 dd      offset dp_irq8,offset dp_irq9,offset dp_irqa,offset dp_irqb
  449.                 dd      offset dp_irqc,offset dp_irqd,offset dp_irqe,offset dp_irqf
  450.                 dd      offset dp_int33,offset dp_int32,offset dp_int33,offset dp_int32
  451. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  452. ; 16 bit DPMI system code
  453. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  454. ;═════════════════════════════════════════════════════════════════════════════
  455. d_retreal:                              ; Return to real mode
  456.         mov ax,205h                     ; restore all int vektorz needed
  457.         mov edi,19
  458. d_retreall0:
  459.         mov bl,ds:intslottbl[edi]
  460.         lea ebp,[edi*2+edi]
  461.         mov edx,dword ptr ds:dp_ointbuf[ebp*2]
  462.         mov cx,word ptr ds:dp_ointbuf[ebp*2+4]
  463.         int 31h
  464.         sub di,1
  465.         jnc d_retreall0
  466.         jmp short d_exit
  467. ;─────────────────────────────────────────────────────────────────────────────
  468. d_exit16err:                            ; DPMI Exit with error message
  469.         mov ds:v86r_ds,code16
  470.         mov ds:v86r_ah,9
  471.         mov ax,300h
  472.         mov bx,21h
  473.         xor cx,cx
  474.         mov edi,offset ds:v86r_edi
  475.         push ds
  476.         pop es
  477.         int 31h
  478. ;─────────────────────────────────────────────────────────────────────────────
  479. d_exit:                                 ; DPMI exit to real mode
  480.         mov es,d_pspsel                 ; restore env selector
  481.         mov ax,d_oldenvsegsel
  482.         mov es:[2ch],ax
  483.         jmp exit
  484. ;═════════════════════════════════════════════════════════════════════════════
  485. d_start:                                ; Start in a crappy DPMI system
  486.         or ds:_sysbyte0,3               ; set system type DPMI byte
  487.  
  488.         test bl,1                       ; must be 32bit DPMI
  489.         mov dx,offset d_errmsg0
  490.         jz exit16err
  491.  
  492.         mov d_enterpmode[0],di          ; store enter addx
  493.         mov d_enterpmode[2],es
  494.         push word ptr fs:[2ch]          ; preserve old env seg
  495.  
  496.         movzx eax,si                    ; get mem for DPMI blok
  497.         shl eax,4
  498.         call pregetlomem
  499.         shr eax,4
  500.         add ax,code32
  501.         mov es,ax
  502.  
  503.         mov ax,1                        ; switch to pmode
  504.         call dword ptr d_enterpmode
  505.         cli                             ; I don't trust DPMI
  506.         mov dx,offset d_errmsg1
  507.         jc exit16err
  508.         mov ds:v86r_dx,dx               ; prepare for abort maybe
  509.         pop ax                          ; swap old env seg with selector
  510.         xchg ax,es:[2ch]
  511.         mov d_oldenvsegsel,ax
  512.         mov d_pspsel,es                 ; store stupid selectors
  513.         mov ds:data16sel,ds
  514.         mov ds:code16sel,cs
  515.         mov ds:code16off,offset d_retreal       ; set return to real mode addx
  516.         mov ds:_setirqvect,offset dp_setirqvect ; modify some crap
  517.         mov ds:_getirqvect,offset dp_getirqvect
  518.         mov ds:_setselector,offset dp_setselector
  519.  
  520.         push ds                         ; no more need for PSP
  521.         pop es
  522.         mov ax,3                        ; get selector increment value
  523.         int 31h
  524.         mov bx,ax
  525.         xor ax,ax                       ; get needed selectors
  526.         mov cx,3+SELECTORS
  527.         int 31h
  528.         jc d_exit16err
  529.  
  530.         mov si,ax                       ; set up descriptors
  531.         mov ds:_selcode,ax
  532.         lea ecx,[eax+ebx]
  533.         mov ds:_seldata,cx
  534.         lea ebp,[ecx+ebx]
  535.         mov ds:_selzero,bp
  536.         lea eax,[ebp+ebx]
  537. if SELECTORS ne 0
  538.         mov ds:selectorbase,ax
  539.         mov ds:selectorinc,bx
  540. endif
  541.         mov ds:v86r_dx,offset d_errmsg2
  542.         mov ax,0ch                      ; set descriptors from GDT
  543.         mov bx,si
  544.         mov edi,offset ds:gdt32code32
  545.         or byte ptr [edi+5],60h
  546.         int 31h
  547.         jc d_exit16err
  548.         mov bx,cx
  549.         mov edi,offset ds:gdt32data32
  550.         or byte ptr [edi+5],60h
  551.         int 31h
  552.         jc d_exit16err
  553.         mov bx,bp
  554.         mov edi,offset ds:gdt32zero32
  555.         or byte ptr [edi+5],60h
  556.         int 31h
  557.         jc d_exit16err
  558. if SELECTORS ne 0
  559.         mov bx,ds:selectorbase          ; set up extra allocatable selectors
  560.         mov dx,SELECTORS
  561. d_startl1:
  562.         int 31h
  563.         jc d_exit16err
  564.         add bx,ds:selectorinc
  565.         dec dx
  566.         jnz d_startl1
  567. endif
  568.         mov es,cx                       ; ES, FS, and GS what they should be
  569.         mov fs,cx
  570.         mov gs,bp
  571.  
  572.         mov edi,ds:_lomembase           ; chek and get extended memory
  573.         mov eax,ds:_lomemtop
  574.         sub eax,edi
  575.         cmp eax,48
  576.         mov ds:v86r_dx,offset errmsg1
  577.         jb d_exit16err
  578.         mov ax,500h
  579.         int 31h
  580.         mov eax,es:[edi+14h]
  581.         cmp eax,-1
  582.         jne short d_startf0
  583.         mov eax,(EXTMIN+3) shr 2
  584. d_startf0:
  585.         shl eax,12
  586.         mov edx,eax
  587.         shr eax,10
  588.         cmp eax,EXTMIN
  589.         mov ds:v86r_dx,offset errmsg3
  590.         jb d_exit16err
  591.         or edx,edx
  592.         jz short d_startf1
  593.         mov cx,dx
  594.         shld ebx,edx,16
  595.         mov ax,501h
  596.         int 31h
  597.         mov ds:v86r_dx,offset errmsg5
  598.         jc d_exit16err
  599.         shl ebx,16
  600.         mov bx,cx
  601.         sub ebx,ds:_code32a
  602.         mov ds:_himembase,ebx
  603.         add ebx,edx
  604.         mov ds:_himemtop,ebx
  605. d_startf1:
  606.  
  607.         mov ax,305h                     ; get save/restore state addxs
  608.         int 31h
  609.         mov ds:dp_savelen,ax
  610.         mov dword ptr ds:dp_saveaddx[0],edi
  611.         mov word ptr ds:dp_saveaddx[4],si
  612.         mov word ptr d_saveaddx[0],cx
  613.         mov word ptr d_saveaddx[2],bx
  614.         mov ax,306h                     ; get switch mode addxs
  615.         int 31h
  616.         mov dword ptr ds:dp_switchaddx[0],edi
  617.         mov word ptr ds:dp_switchaddx[4],si
  618.         mov word ptr d_switchaddx[0],cx
  619.         mov word ptr d_switchaddx[2],bx
  620.  
  621.         mov ax,400h                     ; set IRQ handlers to PIC values
  622.         int 31h
  623.         xchg dl,dh
  624.         mov bx,dx
  625.         call setintslots
  626.  
  627.         mov ah,2                        ; backup and set all int vektorz
  628.         mov si,ds:_selcode
  629.         mov edi,19
  630. d_startl0:
  631.         mov bl,ds:intslottbl[edi]
  632.         mov al,4
  633.         int 31h
  634.         lea ebp,[edi*2+edi]
  635.         mov dword ptr ds:dp_ointbuf[ebp*2],edx
  636.         mov word ptr ds:dp_ointbuf[ebp*2+4],cx
  637.         mov al,5
  638.         mov edx,d_nintoff[edi*4]
  639.         mov cx,si
  640.         int 31h
  641.         sub di,1
  642.         jnc d_startl0
  643.  
  644.         mov ax,es                       ; set up needed regs & go on to 32bit
  645.         mov ss,ax
  646.         add esp,ds:realstackbase
  647.         mov ds,ax
  648.         push dword ptr cs:_selcode
  649.         push offset p_start
  650.         db 66h,0cbh             ; 32bit RETF
  651.  
  652. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  653. ; 16bit VCPI system data
  654. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  655. v_errmsg0       db      'Incompatible VCPI PIC mappings!!!',7,'$'
  656.  
  657. v_pagedirseg    dw      ?               ; seg of page directory
  658. v_pagebase      dw      0               ; first page of himem (*4)+1000h
  659. v_pagetop       dw      0               ; top page of himem (*4)+1000h
  660.  
  661. v_ss_cr3        dd      ?               ; new CR3 for pmode (physical)
  662. v_ss_gdtaddxptr dw      c_gdt32addx,0   ; ptr to GDT data for pmode
  663. v_ss_idtaddxptr dw      c_idt32addx,0   ; ptr to IDT data for pmode
  664. v_ss_ldtsel     dw      0               ; don't need no stinkin LDTs
  665. v_ss_trsel      dw      30h             ; task state segment selector
  666. v_ss_dest       dd      ?               ; start in pmode EIP
  667.                 dw      20h             ; start in pmode CS
  668. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  669. ; 16bit VCPI system code
  670. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  671. ;═════════════════════════════════════════════════════════════════════════════
  672. v_retreal:                              ; VCPI return to real mode
  673.         movzx edi,exitrout
  674.         mov esi,esp
  675.         sub esi,ds:realstackbase
  676.         mov cx,code16
  677. ;═════════════════════════════════════════════════════════════════════════════
  678. ; EDI=offset to jump to, ESI=real mode stack ptr, CX=real mode DS
  679. v_retreal0:                             ; VCPI go to real mode
  680.         sub esp,8
  681.         push ecx
  682.         push dword ptr ds:v86r_es
  683.         dw 06866h,codeend,0     ; PUSH dword codeend
  684.         push esi
  685.         pushfd
  686.         dw 06866h,code16,0      ; PUSH dword code16
  687.         push edi
  688.         mov ax,gs
  689.         mov ds,ax
  690.         mov ax,0de0ch
  691.         call cs:vp_vcpipmentry
  692. ;─────────────────────────────────────────────────────────────────────────────
  693. v_exit:                                 ; VCPI exit (clean up pages)
  694.         mov es,v_pagedirseg
  695.         mov si,v_pagebase
  696.         mov cx,v_pagetop
  697.         sub cx,si
  698.         jz short v_exitf0
  699. v_exitl0:
  700.         mov edx,es:[si]
  701.         and dx,0f000h
  702.         mov ax,0de05h
  703.         int 67h
  704.         add si,4
  705.         sub cx,4
  706.         jnz v_exitl0
  707. v_exitf0:
  708.         jmp exit
  709. ;─────────────────────────────────────────────────────────────────────────────
  710. v_exiterr1:                             ; VCPI not enough low mem exit
  711.         mov dx,offset errmsg1
  712.         jmp exit16err
  713. ;═════════════════════════════════════════════════════════════════════════════
  714. v_start:                                ; start continues from VCPI
  715.         or ds:_sysbyte0,2               ; set system type VCPI byte
  716.         mov ds:code16off,offset v_retreal       ; VCPI return to real mode
  717.         mov c_idt32handler[48h],offset vp_int33 ; VCPI safe int handlers
  718.         mov c_idt32handler[4ch],offset vp_int32
  719.         mov ds:cp_v86irqintr[4],offset vp_int33f0 ; VCPI IRQ safe int routine
  720.         mov int32m0,VINT32              ; VCPI real INT32
  721.  
  722.         mov ax,0de0ah                   ; get PIC mappings
  723.         int 67h
  724.         mov bh,cl
  725.         mov dx,offset v_errmsg0         ; chek for compatible PIC mapping
  726.         cmp bl,bh
  727.         je exit16err
  728.         cmp bl,30h
  729.         je exit16err
  730.         cmp bh,30h
  731.         je exit16err
  732.         mov ax,70h                      ; compatible, get highest needed num
  733.         cmp al,bl
  734.         ja short v_startf1
  735.         mov al,bl
  736. v_startf1:
  737.         cmp al,bh
  738.         ja short v_startf2
  739.         mov al,bh
  740. v_startf2:
  741.         add al,7
  742.         mov c_numofintvects,al
  743.         lea eax,[eax*8+7]               ; set limit of IDT
  744.         mov c_idt32addx,ax
  745.         call setintslots                ; set int slots needed
  746.         movzx eax,ax
  747.         add eax,2068h+1
  748.         call pregetlomem                ; allocate TSS, IO bitmap, and IDT
  749.         mov ds:cp_tssesp0ptr,eax
  750.         mov eax,ds:_code16a             ; adjust mode switch structure
  751.         add dword ptr v_ss_gdtaddxptr,eax
  752.         add dword ptr v_ss_idtaddxptr,eax
  753.  
  754.         mov exitrout,offset v_exit      ; set VCPI cleanup exit
  755.  
  756.         mov eax,ds:_lomembase           ; align lomem base on a page
  757.         mov ebx,ds:_code32a
  758.         add ebx,eax
  759.         lea ecx,[ebx+0fffh]
  760.         and ecx,0fffff000h
  761.         sub ebx,ecx
  762.         sub eax,ebx
  763.         mov ds:_lomembase,eax
  764.         mov ebp,ds:_lomemtop            ; get available low memory
  765.         sub ebp,eax
  766.         sub ebp,LOWMIN*1024             ; die if not enough
  767.         jc v_exiterr1
  768.         cmp ebp,8192
  769.         jb v_exiterr1
  770.  
  771.         shld eax,ecx,28                 ; get segment and clear all pages
  772.         mov v_pagedirseg,ax
  773.         mov es,ax
  774.         xor di,di
  775.         mov cx,2048
  776.         xor eax,eax
  777.         rep stos dword ptr es:[di]
  778.         mov di,1000h                    ; get VCPI pmode interface
  779.         mov esi,offset ds:gdt32vcpi
  780.         mov ax,0de01h
  781.         int 67h
  782.         mov dword ptr ds:vp_vcpipmentry,ebx
  783.  
  784.         mov v_pagebase,di               ; set up and go through allocation
  785.         mov v_pagetop,di
  786.         movzx eax,di
  787.         sub eax,1000h
  788.         shl eax,10
  789.         mov ebp,ds:_code32a
  790.         sub eax,ebp
  791.         mov ds:_himembase,eax
  792.         mov ebx,8192
  793. v_startl2:
  794.         mov ax,0de04h
  795.         int 67h
  796.         or ah,ah
  797.         jnz short v_startl2d
  798.         test di,0fffh
  799.         jnz short v_startf4
  800.         add ebx,4096
  801.         cmp ebx,ebp
  802.         ja v_exiterr1
  803. v_startf4:
  804.         and dx,0f000h
  805.         or dl,7
  806.         mov es:[di],edx
  807.         add di,4
  808.         jnc v_startl2
  809. v_startl2d:
  810.         mov v_pagetop,di
  811.         lea si,[di-1000h]
  812.         movzx eax,si
  813.         shl eax,10
  814.         sub eax,ebp             ; EBP=_code32a
  815.         mov ds:_himemtop,eax
  816.         sub di,v_pagebase
  817.         cmp di,EXTMIN
  818.         mov dx,offset errmsg3
  819.         jb exit16err
  820.         add ds:_lomembase,ebx
  821.  
  822.         movzx ebx,v_pagedirseg          ; set up physical addresses
  823.         shr ebx,8
  824.         mov eax,es:[ebx*4+1000h]
  825.         mov v_ss_cr3,eax
  826.         xor di,di
  827. v_startl3:
  828.         inc ebx
  829.         mov eax,es:[ebx*4+1000h]
  830.         and ax,0f000h
  831.         or al,7
  832.         stos dword ptr es:[di]
  833.         sub si,1000h
  834.         ja v_startl3
  835.  
  836.         mov edi,offset c_startf1        ; offset to jump to in pmode
  837.         mov ebx,ds:cp_tssesp0ptr
  838.         jmp v_switchtopmode             ; duh?
  839.  
  840. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  841. ; 16 bit XMS system data
  842. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  843. x_calladdx      dd      ?               ; XMS driver addx
  844. x_handle        dw      0fedch          ; XMS handle of extended memory
  845. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  846. ; 16 bit XMS system code
  847. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  848. ;─────────────────────────────────────────────────────────────────────────────
  849. x_exit:                                 ; XMS exit (clean up allocation)
  850.         mov ax,cs
  851.         mov ds,ax
  852.         mov dx,x_handle
  853.         mov ah,0dh
  854.         call x_calladdx
  855.         mov ah,0ah
  856.         call x_calladdx
  857.         jmp exit
  858. ;─────────────────────────────────────────────────────────────────────────────
  859. x_exiterr5:                             ; exit with error message 5
  860.         mov dx,offset errmsg5
  861.         jmp exit16err
  862. ;═════════════════════════════════════════════════════════════════════════════
  863. x_start:                                ; start in an XMS system
  864.         or ds:_sysbyte0,1               ; set system type XMS byte
  865.  
  866.         mov ax,4310h                    ; get XMS driver addx
  867.         int 2fh
  868.         mov word ptr x_calladdx[0],bx
  869.         mov word ptr x_calladdx[2],es
  870.  
  871.         mov ah,3                        ; XMS enable A20
  872.         call x_calladdx
  873.         or ax,ax
  874.         mov dx,offset errmsg4
  875.         jz exit16err
  876.  
  877.         mov ah,8                        ; chek and get extended memory
  878.         call x_calladdx
  879.         sub ax,64
  880.         jnc short x_startf0
  881.         xor ax,ax
  882. x_startf0:
  883.         cmp ax,EXTMIN
  884.         mov dx,offset errmsg3
  885.         jb exit16err
  886.         mov dx,ax
  887.         movzx ecx,ax
  888.         shl ecx,10
  889.         mov ah,9
  890.         call x_calladdx
  891.         or ax,ax
  892.         jz x_exiterr5
  893.         mov x_handle,dx
  894.         mov exitrout,offset x_exit
  895.         mov ah,0ch
  896.         call x_calladdx
  897.         or ax,ax
  898.         jz x_exiterr5
  899.         shrd eax,edx,16
  900.         mov ax,bx
  901.         sub eax,ds:_code32a
  902.         mov ds:_himembase,eax
  903.         add eax,ecx
  904.         mov ds:_himemtop,eax
  905.  
  906.         jmp c_startf0                   ; go on to custom start
  907.  
  908. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  909. ; 16 bit custom system data
  910. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  911. c_idt16addx     dw      3ffh, 0,0       ; default real mode IDT addx&limit
  912. c_idt32addx     dw      3bfh, ?,?       ; 32bit IDT addx&limit
  913. c_gdt32addx     dw      04fh+SELECTORS*8; 32bit GDT addx&limit
  914.                 dd      offset gdt32    ;
  915.  
  916. c_numofintvects db      77h             ; number of int vects needed -1
  917. c_idt32handler  dd      offset cp_irq0,offset cp_irq1,offset cp_irq2,offset cp_irq3
  918.                 dd      offset cp_irq4,offset cp_irq5
  919.                 dd      offset cp_irq6,offset cp_irq7,offset cp_irq8,offset cp_irq9
  920.                 dd      offset cp_irqa,offset cp_irqb
  921.                 dd      offset cp_irqc,offset cp_irqd,offset cp_irqe,offset cp_irqf
  922.                 dd      offset cp_int35,offset cp_int34,offset cp_int33,offset cp_int32,offset cp_int31
  923.                 dd      offset cp_exc0,offset cp_exc1,offset cp_exc2,offset cp_exc3
  924.                 dd      offset cp_exc4,offset cp_exc5
  925.                 dd      offset cp_exc6,offset cp_exc7,offset cp_exc8,offset cp_exc9
  926.                 dd      offset cp_exca,offset cp_excb
  927.                 dd      offset cp_excc,offset cp_excd,offset cp_exce
  928. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  929. ; 16 bit custom system code
  930. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  931. ;═════════════════════════════════════════════════════════════════════════════
  932. c_irqreal:                              ; real mode IRQ
  933.         pushf
  934.         push cs
  935.         push offset icreald2
  936.         jmp icreal
  937. ;-----------------------------------------------------------------------------
  938. c_retreal1:                             ; load some real mode stuff & exit
  939.         mov ax,codeend
  940.         mov ss,ax
  941.         mov esp,STAKLEN*10h
  942.         jmp exitrout
  943. ;═════════════════════════════════════════════════════════════════════════════
  944. c_retreal0:                             ; load real mode IDT and set PE=0
  945.         mov ax,28h
  946.         mov ds,ax
  947.         mov es,ax
  948.         mov fs,ax
  949.         mov gs,ax
  950.         mov ss,ax
  951.         lidt fword ptr c_idt16addx
  952.         mov eax,cr0
  953.         and al,0feh
  954.         mov cr0,eax
  955.         db 0eah                 ; JMP FAR PTR c_retreal0m0
  956. c_retreal0m0    dw c_sicreal,code16
  957. ;-----------------------------------------------------------------------------
  958. c_sicreal:                              ; safe real mode int or call
  959.         mov ax,codeend
  960.         mov ss,ax
  961.         mov ds,cs:v86r_ds
  962.         mov es,cs:v86r_es
  963.         db 0eah                 ; JMP FAR PTR c_sicrealm0
  964. c_sicrealm0     dw      ?,code16;
  965. ;═════════════════════════════════════════════════════════════════════════════
  966. c_retreal:                              ; return to real mode
  967.         mov c_retreal0m0,offset c_retreal1
  968.         mov esp,STAKLEN*10h
  969.         jmp c_retreal0
  970. ;═════════════════════════════════════════════════════════════════════════════
  971. c_start:                                ; custom only start
  972.         call enableA20                  ; enable that stupid A20 thingy
  973.  
  974.         mov ah,88h                      ; chek and get extended mem
  975.         int 15h
  976.         cmp ax,EXTMIN
  977.         mov dx,offset errmsg3
  978.         jb exit16err
  979.         movzx eax,ax
  980.         shl eax,10
  981.         mov ebx,100000h
  982.         sub ebx,ds:_code32a
  983.         mov ds:_himembase,ebx
  984.         add eax,ebx
  985.         mov ds:_himemtop,eax
  986. ;═════════════════════════════════════════════════════════════════════════════
  987. c_startf0:                              ; start continues from custom or XMS
  988.         mov int32m0,CINT32              ; raw/XMS real INT32
  989.         mov eax,2428h                   ; allocate TSS, IO bitmap, and IDT
  990.         call pregetlomem
  991.         mov ebx,eax
  992.  
  993.         lgdt fword ptr c_gdt32addx      ; switch to pmode
  994.         mov eax,cr0
  995.         or al,1
  996.         mov cr0,eax
  997.         db 0eah
  998.         dw $+4,20h
  999. ;-----------------------------------------------------------------------------
  1000. ; EBX->TSS
  1001. c_startf1:                              ; in 16bit pmode
  1002.         mov ax,28h                      ; set up segregs
  1003.         mov ds,ax
  1004.         mov al,18h
  1005.         mov gs,ax
  1006.         mov al,10h
  1007.         mov es,ax
  1008.         mov fs,ax
  1009.         mov ss,ax
  1010.         mov esp,STAKLEN*16
  1011.         add esp,ds:realstackbase
  1012.  
  1013.         mov word ptr v_ss_dest[4],8     ; VCPI enter 32bit pmode from now on
  1014.         lea eax,[ebx+4]                 ; addx of ESP0 in TSS
  1015.         mov ds:cp_tssesp0ptr,eax
  1016.         mov ebp,ds:_code32a             ; TSS location in mem to GDT
  1017.         lea eax,[ebx+ebp]
  1018.         mov ecx,offset ds:gdt32task     ; set up task
  1019.         or dword ptr ds:[ecx+2],eax
  1020.         mov byte ptr ds:[ecx+5],89h
  1021.         mov cx,30h
  1022.         ltr cx
  1023.         add eax,2068h                   ; set up IDT
  1024.         mov ecx,offset c_idt32addx
  1025.         mov dword ptr [ecx+2],eax
  1026.         lidt fword ptr [ecx]
  1027.  
  1028.         mov dword ptr es:[ebx+8],10h    ; set up TSS stuff (EBX->TSS)
  1029.         mov edi,104
  1030.         mov es:[ebx+102],di
  1031.         mov word ptr es:[ebx+100],0
  1032.         add edi,ebx                     ; fill IO bitmap with 0
  1033.         xor eax,eax
  1034.         mov ecx,800h
  1035.         rep stos dword ptr es:[edi]
  1036.  
  1037.         mov ds:cp_idt32ptr,edi          ; set up blank IDT entries
  1038.         movzx esi,c_numofintvects
  1039. c_startl0:
  1040.         mov dword ptr es:[edi+esi*8],80000h+offset cp_excf
  1041.         mov dword ptr es:[edi+esi*8+4],8e00h
  1042.         sub si,1
  1043.         jnc c_startl0
  1044.         mov si,23h                      ; necessary IDT entries
  1045. c_startl1:
  1046.         movzx ebp,ds:intslottbl[esi]
  1047.         mov eax,c_idt32handler[esi*4]
  1048.         cmp bp,13
  1049.         jne short c_startl1c
  1050.         mov ds:cp_int13vect,eax
  1051.         mov eax,offset cp_excd
  1052. c_startl1c:
  1053.         mov es:[edi+ebp*8],ax
  1054.         sub si,1
  1055.         jnc c_startl1
  1056.  
  1057.         mov edi,offset p_start          ; set up regs & go on to 32bit
  1058.     mov ax,10h
  1059.         mov ds,ax
  1060. ;-----------------------------------------------------------------------------
  1061. c_gotopmode:                ; jump to 32bit pmode
  1062.         pushfd                          ; set eflags: NT=0, IOPL=3
  1063.         pop eax
  1064.         and ah,0bfh
  1065.         or ah,30h
  1066.         push eax
  1067.         popfd
  1068.         dw 6866h,8,0            ; PUSH dword 8
  1069.     push edi
  1070.         db 66h,0cbh             ; 32bit RETF
  1071.  
  1072. code16  ends
  1073.  
  1074. ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  1075. ; 32bit pmode code
  1076. ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  1077. code32  segment para public use32
  1078.         assume cs:code32, ds:code32
  1079.         org 0
  1080.  
  1081. extrn   _main:near
  1082.  
  1083. public  _exit, _ret, _getmem, _getlomem, _gethimem, _lomemsize, _himemsize
  1084. public  _getirqmask, _setirqmask, _getselector, _freeselector, _rmpmirqset
  1085. public  _rmpmirqfree
  1086.  
  1087. public  v86r_eax, v86r_ebx, v86r_ecx, v86r_edx, v86r_esi, v86r_edi, v86r_ebp
  1088. public  v86r_ax, v86r_bx, v86r_cx, v86r_dx, v86r_si, v86r_di, v86r_bp
  1089. public  v86r_al, v86r_ah, v86r_bl, v86r_bh, v86r_cl, v86r_ch, v86r_dl, v86r_dh
  1090. public  v86r_ds, v86r_es, v86r_fs, v86r_gs
  1091. public  _selcode, _seldata, _selzero, _lomembase, _lomemtop, _himembase
  1092. public  _himemtop, _pspa, _code16a, _code32a, _getirqvect, _setirqvect
  1093. public  _sysbyte0, _irqmode, _setselector
  1094. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1095. ; 32 bit common system data
  1096. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1097. _lomembase      dd      ?               ; low mem base for allocation
  1098. _lomemtop       dd      ?               ; top of low mem
  1099. _himembase      dd      0               ; high mem base for allocation
  1100. _himemtop       dd      0               ; top of high mem
  1101. _pspa           dd      ?               ; offset of start of PSP from 0
  1102. _code16a        dd      ?               ; offset of start of 16bit code from 0
  1103. _code32a        dd      ?               ; offset of start of 32bit code from 0
  1104. _selcode        dw      8               ; code segment selector
  1105. _seldata        dw      10h             ; data segment alias for code
  1106. _selzero        dw      18h             ; data segment starting at 0:0
  1107. _irqmode        dw      0ffffh          ; IRQ mode bits: 0=normal, 1=safe
  1108.                 db      0ffh            ; misc byte, has to follow _irqmode
  1109. _sysbyte0       db      0               ; system bits:
  1110.                                         ;  0-1: 0=raw, 1=XMS, 2=VCPI, 3=DPMI
  1111.  
  1112. align 4
  1113. _getirqvect     dd      cp_getirqvect   ; get IRQ handler offset routine addx
  1114. _setirqvect     dd      cp_setirqvect   ; set IRQ handler offset routine addx
  1115. _setselector    dd      cp_setselector  ; set a selector addx offset addx
  1116.  
  1117. gdt32           dq      0
  1118. gdt32code32     db      0ffh,0ffh,0,0,0,9ah,0cfh,0
  1119. gdt32data32     db      0ffh,0ffh,0,0,0,92h,0cfh,0
  1120. gdt32zero32     db      0ffh,0ffh,0,0,0,92h,0cfh,0
  1121. gdt32code16     db      0ffh,0ffh,0,0,0,9ah,0,0
  1122. gdt32data16     db      0ffh,0ffh,0,0,0,92h,0,0
  1123. gdt32task       db      0ffh,0ffh,0,0,0,89h,0,0
  1124. gdt32vcpi       dq      3 dup(?)
  1125. if SELECTORS ne 0
  1126. gdt32free       db      SELECTORS dup(0ffh,0ffh,0,0,0,92h,0cfh,0)
  1127. endif
  1128.  
  1129. v86r_edi        label   dword           ; vregs for pmode<>real communication
  1130. v86r_di         dw      ?, ?            ;  needz to stay this way cuz its a
  1131. v86r_esi        label   dword           ;  stupid DPMI structure thingy
  1132. v86r_si         dw      ?, ?
  1133. v86r_ebp        label   dword
  1134. v86r_bp         dw      ?, ?
  1135.                 dd      0
  1136. v86r_ebx        label   dword
  1137. v86r_bx         label   word
  1138. v86r_bl         db      ?
  1139. v86r_bh         db      ?, ?,?
  1140. v86r_edx        label   dword
  1141. v86r_dx         label   word
  1142. v86r_dl         db      ?
  1143. v86r_dh         db      ?, ?,?
  1144. v86r_ecx        label   dword
  1145. v86r_cx         label   word
  1146. v86r_cl         db      ?
  1147. v86r_ch         db      ?, ?,?
  1148. v86r_eax        label   dword
  1149. v86r_ax         label   word
  1150. v86r_al         db      ?
  1151. v86r_ah         db      ?, ?,?
  1152. v86r_flags      dw      ?
  1153. v86r_es         dw      ?
  1154. v86r_ds         dw      ?
  1155. v86r_fs         dw      ?
  1156. v86r_gs         dw      ?
  1157.                 dd      0,0
  1158.  
  1159. oint1bvect      dd      ?               ; old real int 1bh vektor (ctrl+break)
  1160. oint32vect      dd      ?               ; old real int 32h vector
  1161. oirqmask        dw      ?               ; old port 21h and 0a1h masks
  1162. intslottbl      db      8,9,0ah,0bh,0ch,0dh,0eh,0fh,70h,71h,72h,73h,74h,75h,76h,77h
  1163.                 db      35h,34h,33h,32h,31h,0,1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0eh
  1164.  
  1165. if SELECTORS ne 0
  1166. selectorbase    dw      50h
  1167. selectorinc     dw      8
  1168. selectorfree    db      SELECTORS dup(0)
  1169. endif
  1170.  
  1171. code16off       dw      c_retreal       ; offset in 16bit of exit function
  1172. code16sel       dw      20h             ; 16bit pmode code selector
  1173. data16sel       dw      28h             ; 16bit pmode data selector
  1174.  
  1175. nextmodestack   dw      (STAKLEN-STAKSAFE)*16   ; stack for next mode switch
  1176. realstackbase   dd      ?               ; linear ptr to beginning of codeend
  1177.  
  1178. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1179. ; 32 bit common system code
  1180. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1181. ;═════════════════════════════════════════════════════════════════════════════
  1182. p_cpmode2:                ; call pmode from V86
  1183.         mov gs,cx
  1184.         mov cl,10h
  1185.         mov ds,cx
  1186.         mov es,cx
  1187.         mov fs,cx
  1188.     sub nextmodestack,STAKSAFE*16
  1189.     push p_cpmodem2
  1190.     mov p_cpmodem2,V86CPMODED
  1191.         mov eax,[esp+22]
  1192.     mov p_cpmodem0,eax
  1193.         mov al,[esp+43]
  1194.     shr al,1
  1195.     and al,1
  1196.     add al,0fah
  1197.     mov p_cpmodem1,al
  1198.         jmp short p_cpmode
  1199. ;═════════════════════════════════════════════════════════════════════════════
  1200. p_cpmode1:                              ; call pmode, load all
  1201.         mov esp,ebx
  1202.         mov ax,10h
  1203.         mov ds,ax
  1204.         mov es,ax
  1205.         mov ss,ax
  1206. ;-----------------------------------------------------------------------------
  1207. p_cpmode0:                              ; call pmode, load FS and GS
  1208.         mov fs,_seldata
  1209.         mov gs,_selzero
  1210. ;-----------------------------------------------------------------------------
  1211. p_cpmode:                               ; call pmode routine from real
  1212.         push offset p_cpmoded
  1213.         cld
  1214.         mov eax,v86r_eax
  1215.         mov ecx,v86r_ecx
  1216.         mov edx,v86r_edx
  1217.         mov ebx,v86r_ebx
  1218.         mov esi,v86r_esi
  1219.         mov edi,v86r_edi
  1220.         mov ebp,v86r_ebp
  1221.         db 68h                  ; PUSH destination address
  1222. p_cpmodem0      dd      ?       ;
  1223. p_cpmodem1      db      ?       ; CLI or STI
  1224.         ret
  1225. ;-----------------------------------------------------------------------------
  1226. p_cpmoded:                              ; call to pmode done
  1227.         cli
  1228.         pushf
  1229.         pop v86r_flags
  1230.         mov v86r_eax,eax
  1231.         mov v86r_ecx,ecx
  1232.         mov v86r_edx,edx
  1233.         mov v86r_ebx,ebx
  1234.         mov v86r_esi,esi
  1235.         mov v86r_edi,edi
  1236.         mov v86r_ebp,ebp
  1237.         mov ecx,_code16a
  1238. p_cpmodem2        label word            ; return to real, modifiable to JMP
  1239. ;-----------------------------------------------------------------------------
  1240.         movzx ebx,gs:savedstakoff[ecx]  ; DPMI return to real mode
  1241.         mov dx,gs:savedstakseg[ecx]
  1242.         mov ax,code16
  1243.         mov cx,dx
  1244.         mov si,ax
  1245.         mov edi,offset int32d0
  1246.         jmp dp_switchaddx
  1247. ;-----------------------------------------------------------------------------
  1248. VCPMODED=(($-(p_cpmodem2+2))shl 8)+0ebh
  1249. p_cpmoded2:                             ; VCPI done with pmode
  1250.         movzx esi,gs:savedstakoff[ecx]
  1251.         mov cx,code16
  1252.         mov edi,offset int32d1
  1253.         db 0eah                 ; 16bit JMP FAR 20h:v_retreal0
  1254.         dw v_retreal0,0,20h     ;
  1255. ;-----------------------------------------------------------------------------
  1256. CCPMODED=(($-(p_cpmodem2+2))shl 8)+0ebh
  1257. p_cpmoded3:                             ; raw/XMS done with pmode
  1258.         mov gs:c_retreal0m0[ecx],offset int32d3
  1259.         db 0eah                 ; 16bit JMP FAR 20h:c_retreal0
  1260.         dw c_retreal0,0,20h     ;
  1261. ;-----------------------------------------------------------------------------
  1262. if ($-(p_cpmodem2+2)) gt 127
  1263.   err
  1264. endif
  1265. V86CPMODED=(($-(p_cpmodem2+2))shl 8)+0ebh
  1266. p_cpmoded4:                ; V86 done with pmode
  1267.     pop p_cpmodem2
  1268.         jmp cp_int3_d3
  1269. ;═════════════════════════════════════════════════════════════════════════════
  1270. p_start:                                ; common 32bit start
  1271.         mov eax,gs:[1bh*4]              ; neutralize crtl+break
  1272.         mov oint1bvect,eax
  1273.         db 65h,67h,0c7h,6       ; MOV DWORD PTR GS:[1bh*4],code16:nullint
  1274.         dw 1bh*4,nullint,code16 ;
  1275.         mov eax,gs:[32h*4]              ; set up for new real mode INT32
  1276.         mov oint32vect,eax
  1277.         db 65h,67h,0c7h,6       ; MOV DWORD PTR GS:[32h*4],code16:int32
  1278.         dw 32h*4,int32,code16   ;
  1279.         in al,21h                       ; save old PIC masks
  1280.         mov ah,al
  1281.         in al,0a1h
  1282.         mov oirqmask,ax
  1283.         jmp _main                       ; go to main code
  1284.  
  1285. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1286. ; Allocate any mem, (first cheks low, then high)
  1287. ; In:
  1288. ;   EAX - size requested
  1289. ; Out:
  1290. ;   CF=0 - memory allocated
  1291. ;   CF=1 - not enough mem
  1292. ;   EAX - linear pointer to mem or ?
  1293. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1294. _getmem:
  1295.         push eax
  1296.         call _getlomem
  1297.         jnc short getmemd
  1298.         pop eax
  1299.         jmp short _gethimem
  1300. getmemd:
  1301.         add esp,4
  1302. _ret:                                   ; generic RET instruction
  1303.         ret
  1304. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1305. ; Allocate some low mem
  1306. ; In:
  1307. ;   EAX - size requested
  1308. ; Out:
  1309. ;   CF=0 - memory allocated
  1310. ;   CF=1 - not enough mem
  1311. ;   EAX - linear pointer to mem or ?
  1312. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1313. _getlomem:
  1314.         add eax,_lomembase
  1315.         cmp eax,_lomemtop
  1316.         ja short getmemerr
  1317.         xchg eax,_lomembase
  1318.         clc
  1319.         ret
  1320. getmemerr:
  1321.         stc
  1322.         ret
  1323. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1324. ; Allocate some high mem
  1325. ; In:
  1326. ;   EAX - size requested
  1327. ; Out:
  1328. ;   CF=0 - memory allocated
  1329. ;   CF=1 - not enough mem
  1330. ;   EAX - linear pointer to mem or ?
  1331. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1332. _gethimem:
  1333.         add eax,_himembase
  1334.         cmp eax,_himemtop
  1335.         ja short getmemerr
  1336.         xchg eax,_himembase
  1337.         clc
  1338.         ret
  1339. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1340. ; Get amount of free low mem
  1341. ; Out:
  1342. ;   EAX - number of bytes free
  1343. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1344. _lomemsize:
  1345.         mov eax,_lomemtop
  1346.         sub eax,_lomembase
  1347.         ret
  1348. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1349. ; Get amount of free high mem
  1350. ; Out:
  1351. ;   EAX - number of bytes free
  1352. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1353. _himemsize:
  1354.         mov eax,_himemtop
  1355.         sub eax,_himembase
  1356.         ret
  1357. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1358. ; Get status of IRQ mask bit
  1359. ; In:
  1360. ;   BL - IRQ num (0-15)
  1361. ; Out:
  1362. ;   AL - status: 0=enabled, 1=disabled
  1363. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1364. _getirqmask:
  1365.         push ax
  1366.         in al,0a1h
  1367.         mov ah,al
  1368.         in al,21h
  1369.         xchg cl,bl
  1370.         shr ax,cl
  1371.         xchg cl,bl
  1372.         and al,1
  1373.         mov [esp],al
  1374.         pop ax
  1375.         ret
  1376. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1377. ; Set status of IRQ mask bit
  1378. ; In:
  1379. ;   BL - IRQ num (0-15)
  1380. ;   AL - status: 0=enabled, 1=disabled
  1381. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1382. _setirqmask:
  1383.         push ax bx cx dx
  1384.         mov cl,bl
  1385.         mov bx,0fffeh
  1386.         movzx dx,al
  1387.         rol bx,cl
  1388.         shl dx,cl
  1389.         in al,0a1h
  1390.         mov ah,al
  1391.         in al,21h
  1392.         and ax,bx
  1393.         or ax,dx
  1394.         out 21h,al
  1395.         mov al,ah
  1396.         out 0a1h,al
  1397.         pop dx cx bx ax
  1398.         ret
  1399. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1400. ; Set a real mode IRQ vect to redirect to pmode
  1401. ; In:
  1402. ;   BL - IRQ number
  1403. ;   EDI -> 21 byte buffer for code stub created
  1404. ; Out:
  1405. ;   EDX - old seg:off of real mode IRQ handler
  1406. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1407. rmpmirqsetd0:
  1408. db 66h,52h              ; PUSH EDX
  1409. db 66h,0bah,?,?,?,?     ; MOV EDX,?
  1410. db 0cdh,32h             ; INT 32h
  1411. db 66h,5ah              ; POP EDX
  1412. db 0cfh                 ; IRET
  1413. db 9ch                  ; PUSHFD
  1414. db 0eh                  ; PUSH CS
  1415. db 0e8h,?,?,?,?         ; CALL ?
  1416. db 0c3h                 ; RET
  1417. ;-----------------------------------------------------------------------------
  1418. _rmpmirqset:
  1419.         push eax esi edi
  1420.         mov esi,offset rmpmirqsetd0
  1421.         lea eax,[edi+13]
  1422.         mov [esi+4],eax
  1423.         call _getirqvect
  1424.         add eax,7
  1425.         sub edx,eax
  1426.         mov [esi+16],edx
  1427.         mov edx,edi
  1428.         movsd
  1429.         movsd
  1430.         movsd
  1431.         movsd
  1432.         movsd
  1433.         movsb
  1434.         add edx,_code32a
  1435.         shl edx,12
  1436.         shr dx,12
  1437.         movzx eax,bl
  1438.         cmp al,8
  1439.         jb short rmpmirqsetf0
  1440.         add al,60h
  1441. rmpmirqsetf0:
  1442.         xchg edx,gs:[eax*4+20h]
  1443.         pop edi esi eax
  1444.         ret
  1445. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1446. ; Reset a real more IRQ vect back to normal (just sets real mode IRQ vect)
  1447. ; In:
  1448. ;   BL - IRQ number
  1449. ;   EDX - seg:off of real mode IRQ handler
  1450. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1451. _rmpmirqfree:
  1452.         push ebx
  1453.         movzx ebx,bl
  1454.         cmp bl,8
  1455.         jb short rmpmirqfreef0
  1456.         add bl,60h
  1457. rmpmirqfreef0:
  1458.         mov gs:[ebx*4+20h],edx
  1459.         pop ebx
  1460.         ret
  1461. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1462. ; Allocate a selector
  1463. ; Out:
  1464. ;   CF=1 - selector not allocated
  1465. ;   CF=0 - selector allocated
  1466. ;     AX - 4G data selector or ?
  1467. ; Notes:
  1468. ;   The selector returned is for a 4G r/w data segment with an undefined base
  1469. ;    address.
  1470. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1471. _getselector:
  1472. if SELECTORS eq 0
  1473.         stc
  1474.         ret
  1475. else
  1476.         push ecx edi
  1477.         mov edi,offset selectorfree
  1478.         mov ecx,SELECTORS
  1479.         mov al,0
  1480.         repne scasb
  1481.         jne short getselectorf0
  1482.         mov byte ptr [edi-1],1
  1483.         sub ecx,SELECTORS-1
  1484.         neg ecx
  1485.         imul cx,selectorinc
  1486.         mov ax,selectorbase
  1487.         add ax,cx
  1488.         clc
  1489.         jmp short getselectorf1
  1490. getselectorf0:
  1491.         stc
  1492. getselectorf1:
  1493.         pop edi ecx
  1494.         ret
  1495. endif
  1496. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1497. ; Free an allocated selector
  1498. ; In:
  1499. ;   AX - selector
  1500. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1501. _freeselector:
  1502. if SELECTORS ne 0
  1503.         push eax dx
  1504.         sub ax,selectorbase
  1505.         xor dx,dx
  1506.         div selectorinc
  1507.         movzx eax,ax
  1508.         mov selectorfree[eax],0
  1509.         pop dx eax
  1510. endif
  1511.         ret
  1512. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1513. ; Exit to real mode
  1514. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1515. _exit:
  1516.         cli
  1517.         mov eax,oint1bvect              ; restore ctrl+break
  1518.         mov gs:[1bh*4],eax
  1519.         mov eax,oint32vect              ; restore real mode int 32h vector
  1520.         mov gs:[32h*4],eax
  1521.         mov ax,oirqmask                 ; restore PIC masks
  1522.         out 0a1h,al
  1523.         mov al,ah
  1524.         out 21h,al
  1525.         push code16sel                  ; go to 16bit pmode exit code
  1526.         push code16off
  1527.         mov ds,data16sel
  1528.         db 66h,0cbh             ; 16bit RETF
  1529.  
  1530. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1531. ; 32 bit DPMI system data
  1532. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1533. dp_switchaddx   df      ?               ; switch to real mode addx
  1534. dp_saveaddx     df      ?               ; save/restore state addx
  1535. dp_savelen      dw      0,0             ; length of state buffer
  1536. dp_savedstaksel dw      ?               ; current saved stack selector
  1537.  
  1538. dp_ointbuf      df      20 dup(?)       ; saved interrupt addx buffer
  1539. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1540. ; 32 bit DPMI system code
  1541. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1542. ;═════════════════════════════════════════════════════════════════════════════
  1543. dp_int32:                               ; DPMI INT32/34: CX:DX=seg:off
  1544.         pushad
  1545.         shl ecx,16
  1546.         mov cx,dx
  1547.         mov bp,offset callreal
  1548.         mov dl,1
  1549.         jmp short dp_int3_
  1550. ;═════════════════════════════════════════════════════════════════════════════
  1551. dp_int33:                               ; DPMI INT33/35: AL=int num
  1552.         pushad
  1553.         movzx eax,al
  1554.         mov ecx,gs:[eax*4]
  1555.         mov bp,offset intreal
  1556.         xor dl,dl
  1557. ;-----------------------------------------------------------------------------
  1558. dp_int3_:                               ; DPMI int or call to real mode
  1559.         mov ax,900h
  1560.         int 31h
  1561.         push ax
  1562.         and al,dl
  1563.         add al,0fah
  1564.         mov ebx,_code16a
  1565.         mov gs:icrealm0[ebx],al
  1566.         mov gs:icrealm1[ebx],ecx
  1567.         push cp_savedstakoff
  1568.         push dp_savedstaksel
  1569.         movzx ebx,nextmodestack
  1570.         lea eax,[ebx-STAKSAFE*16]
  1571.         mov nextmodestack,ax
  1572.         mov ax,ss
  1573.         mov es,ax
  1574.         sub esp,dword ptr dp_savelen
  1575.         mov edi,esp
  1576.         xor al,al
  1577.         call dp_saveaddx
  1578.         mov cp_savedstakoff,esp
  1579.         mov dp_savedstaksel,ss
  1580.         mov dx,codeend
  1581.         mov ax,v86r_ds
  1582.         mov cx,v86r_es
  1583.         movzx edi,bp
  1584.         mov si,code16
  1585.         jmp dp_switchaddx
  1586. ;-----------------------------------------------------------------------------
  1587. dp_int3_d:                              ; done with real mode int or call
  1588.         mov edi,esp
  1589.         mov al,1
  1590.         call dp_saveaddx
  1591.         add esp,dword ptr dp_savelen
  1592.         pop dp_savedstaksel
  1593.         pop cp_savedstakoff
  1594.         add nextmodestack,STAKSAFE*16
  1595.         mov bx,v86r_flags
  1596.         pop ax
  1597.         int 31h
  1598.         mov ax,ds
  1599.         mov es,ax
  1600.         mov fs,ax
  1601.         mov gs,_selzero
  1602.         jmp cp_int3_d2
  1603. ;═════════════════════════════════════════════════════════════════════════════
  1604. ; DPMI IRQ redirectors (needed to make all IRQ vector selectors = CS)
  1605. dp_irq0:
  1606.         jmp cs:dp_ointbuf[0]
  1607. dp_irq1:
  1608.         jmp cs:dp_ointbuf[6]
  1609. dp_irq2:
  1610.         jmp cs:dp_ointbuf[12]
  1611. dp_irq3:
  1612.         jmp cs:dp_ointbuf[18]
  1613. dp_irq4:
  1614.         jmp cs:dp_ointbuf[24]
  1615. dp_irq5:
  1616.         jmp cs:dp_ointbuf[30]
  1617. dp_irq6:
  1618.         jmp cs:dp_ointbuf[36]
  1619. dp_irq7:
  1620.         jmp cs:dp_ointbuf[42]
  1621. dp_irq8:
  1622.         jmp cs:dp_ointbuf[48]
  1623. dp_irq9:
  1624.         jmp cs:dp_ointbuf[54]
  1625. dp_irqa:
  1626.         jmp cs:dp_ointbuf[60]
  1627. dp_irqb:
  1628.         jmp cs:dp_ointbuf[66]
  1629. dp_irqc:
  1630.         jmp cs:dp_ointbuf[72]
  1631. dp_irqd:
  1632.         jmp cs:dp_ointbuf[78]
  1633. dp_irqe:
  1634.         jmp cs:dp_ointbuf[84]
  1635. dp_irqf:
  1636.         jmp cs:dp_ointbuf[90]
  1637.  
  1638. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1639. ; DPMI get IRQ handler offset
  1640. ; In:
  1641. ;   BL - IRQ num (0-0fh)
  1642. ; Out:
  1643. ;   EDX - offset of IRQ handler
  1644. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1645. dp_getirqvect:
  1646.         push ax ebx cx
  1647.         movzx ebx,bl
  1648.         mov bl,intslottbl[ebx]
  1649.         mov ax,204h
  1650.         int 31h
  1651.         pop cx ebx ax
  1652.         ret
  1653. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1654. ; DPMI set IRQ handler offset
  1655. ; In:
  1656. ;   BL - IRQ num (0-0fh)
  1657. ;   EDX - offset of IRQ handler
  1658. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1659. dp_setirqvect:
  1660.         push ax ebx cx
  1661.         movzx ebx,bl
  1662.         mov bl,intslottbl[ebx]
  1663.         mov cx,cs
  1664.         mov ax,205h
  1665.         int 31h
  1666.         pop cx ebx ax
  1667.         ret
  1668. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1669. ; Set the base addx for a selector
  1670. ; In:
  1671. ;   AX - selector
  1672. ;   EDX - linear base addx for selector
  1673. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1674. dp_setselector:
  1675. if SELECTORS ne 0
  1676.         push ax bx ecx
  1677.         shld ecx,edx,16
  1678.         mov bx,ax
  1679.         mov ax,7
  1680.         int 31h
  1681.         pop ecx bx ax
  1682. endif
  1683.         ret
  1684.  
  1685. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1686. ; 32 bit custom/XMS/VCPI system data
  1687. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1688. vp_vcpipmentry  df      3800000000h     ; VCPI entry point in pmode
  1689.  
  1690. cp_tssesp0ptr   dd      0               ; ptr to ESP0 in TSS, or null in VCPI
  1691. cp_idt32ptr     dd      ?               ; ptr to 32bit IDT
  1692. cp_int13vect    dd      0               ; interrupt vektor 13 ptr
  1693. cp_validirqesp  dd      0               ; valid IRQ ESP value for exc 13
  1694.  
  1695. cp_v86irqintr   dd      cp_int35f1,cp_int33f0   ; IRQ int call routines
  1696. cp_v86irqnum    db      ?               ; IRQ num for V86 mode
  1697. cp_v86irqmode   db      ?               ; IRQ mode for V86 mode (safe/norm)
  1698. cp_savedstakoff dd      ?               ; current saved stack offset
  1699. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1700. ; 32 bit custom/XMS/VCPI system code
  1701. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1702. ;═════════════════════════════════════════════════════════════════════════════
  1703. cp_int31:                               ; INT 31h: AX=900h,901h,902h
  1704.         cmp al,1
  1705.         mov al,[esp+9]
  1706.         jb short cp_int31f0
  1707.         ja short cp_int31f1
  1708.         or byte ptr [esp+9],2
  1709.         jmp short cp_int31f1
  1710. cp_int31f0:
  1711.         and byte ptr [esp+9],0fdh
  1712. cp_int31f1:
  1713.         shr al,1
  1714.         and al,1
  1715.         iretd
  1716. ;═════════════════════════════════════════════════════════════════════════════
  1717. vp_int32:                               ; VCPI INT 32h: safe CX:DX=seg:off
  1718.         pushad
  1719.         mov ebp,offset callreal
  1720.         mov si,VICREAL1D
  1721.         mov bl,2
  1722.         jmp short cp_int34f0
  1723. ;═════════════════════════════════════════════════════════════════════════════
  1724. vp_int33:                               ; VCPI INT 33h: safe AL=int num
  1725.         pushad
  1726.         mov ebp,offset intreal
  1727. ;-----------------------------------------------------------------------------
  1728. vp_int33f0:
  1729.         mov si,VICREAL1D
  1730.         mov bl,2
  1731.         jmp short cp_int35f0
  1732. ;═════════════════════════════════════════════════════════════════════════════
  1733. cp_int32:                               ; INT 32h: safe CX:DX=seg:off
  1734.         pushad
  1735.         mov ebp,offset callreal
  1736.         mov si,CICREAL1D
  1737.         mov bl,1
  1738.         jmp short cp_int34f0
  1739. ;═════════════════════════════════════════════════════════════════════════════
  1740. cp_int33:                               ; INT 33h: safe AL=int num
  1741.         pushad
  1742.         mov ebp,offset intreal
  1743. ;-----------------------------------------------------------------------------
  1744. cp_int33f0:
  1745.         mov si,CICREAL1D
  1746.         mov bl,1
  1747.         jmp short cp_int35f0
  1748. ;═════════════════════════════════════════════════════════════════════════════
  1749. cp_int34:                               ; INT 34h: normal CX:DX=seg:off
  1750.         pushad
  1751.         mov ebp,offset callreal
  1752.         mov si,CICREAL0D
  1753.         xor bl,bl
  1754. ;-----------------------------------------------------------------------------
  1755. cp_int34f0:
  1756.         shl ecx,16
  1757.         mov cx,dx
  1758.         mov bh,1
  1759.         jmp short cp_int3_
  1760. ;═════════════════════════════════════════════════════════════════════════════
  1761. cp_int35:                               ; INT 35h: normal AL=int num
  1762.         pushad
  1763.         mov ebp,offset intreal
  1764. ;-----------------------------------------------------------------------------
  1765. cp_int35f1:
  1766.         mov si,CICREAL0D
  1767.         xor bl,bl
  1768. ;-----------------------------------------------------------------------------
  1769. cp_int35f0:
  1770.         movzx eax,al
  1771.         mov ecx,gs:[eax*4]
  1772.         xor bh,bh
  1773. ;-----------------------------------------------------------------------------
  1774. cp_int3_:                               ; int or call to real mode
  1775.         mov edi,[esp+40]
  1776.         shld eax,edi,23
  1777.         and al,bh
  1778.         add al,0fah
  1779.         mov edx,_code16a
  1780.         mov gs:icrealm0[edx],al
  1781.         mov gs:icrealm1[edx],ecx
  1782.         xchg gs:icrealm2[edx],si
  1783.         push si
  1784.         movzx esi,nextmodestack
  1785.         lea eax,[esi-STAKSAFE*16]
  1786.         mov nextmodestack,ax
  1787.         add eax,realstackbase
  1788.         mov edx,cp_tssesp0ptr
  1789.         push dword ptr [edx]
  1790.         mov [edx],eax
  1791.         sub eax,36
  1792.         push cp_validirqesp
  1793.         mov cp_validirqesp,eax
  1794.         push cp_savedstakoff
  1795.         mov cp_savedstakoff,esp
  1796.         cmp bl,1
  1797.         jb short cp_int3_n
  1798.         ja short vp_int3_s
  1799. ;-----------------------------------------------------------------------------
  1800. cp_int3_s:                              ; safe real mode int or call
  1801.         mov edx,_code16a
  1802.         mov gs:c_sicrealm0[edx],bp
  1803.         mov esp,esi
  1804.         db 0eah                 ; 16bit JMP FAR 20h:c_retreal0
  1805.         dw c_retreal0,0,20h     ;
  1806. ;-----------------------------------------------------------------------------
  1807. vp_int3_s:                              ; safe VCPI real mode int or call
  1808.         mov edi,ebp
  1809.         mov cx,v86r_ds
  1810.         mov ax,28h
  1811.         mov ds,ax
  1812.         db 0eah                 ; 16bit JMP FAR 20h:v_retreal0
  1813.         dw v_retreal0,0,20h     ;
  1814. ;-----------------------------------------------------------------------------
  1815. cp_int3_n:                              ; normal real mode int or call
  1816.         sub esp,8
  1817.         push dword ptr v86r_ds
  1818.         push dword ptr v86r_es
  1819.         db 68h                  ; 32bit PUSH codeend
  1820.         dd codeend              ;
  1821.         push esi
  1822.         or edi,20000h
  1823.         and di,0fdffh
  1824.         push edi
  1825.         db 68h                  ; 32bit PUSH code16
  1826.         dd code16               ;
  1827.         push ebp
  1828.         iretd
  1829. ;-----------------------------------------------------------------------------
  1830. cp_int3_d:                              ; done with real mode int or call
  1831.         mov ax,18h
  1832.         mov gs,ax
  1833.         mov ax,10h
  1834.         mov ds,ax
  1835.         mov es,ax
  1836.         mov fs,ax
  1837.         mov ss,ax
  1838.         mov esp,cp_savedstakoff
  1839.         pop cp_savedstakoff
  1840.         pop cp_validirqesp
  1841.         mov ebx,cp_tssesp0ptr
  1842.         pop dword ptr [ebx]
  1843.         mov ebx,_code16a
  1844.         pop gs:icrealm2[ebx]
  1845. ;-----------------------------------------------------------------------------
  1846. cp_int3_d3:                             ; done from real mode pmode call
  1847.         add nextmodestack,STAKSAFE*16
  1848.         mov bx,v86r_flags
  1849. ;-----------------------------------------------------------------------------
  1850. cp_int3_d2:                ; done from DPMI also
  1851.         mov ax,[esp+40]
  1852.         and ax,not 8d5h
  1853.         and bx,8d5h
  1854.         or ax,bx
  1855.         mov [esp+40],ax
  1856.         popad
  1857.         iretd
  1858. ;═════════════════════════════════════════════════════════════════════════════
  1859. cp_excd:                                ; general protection violation
  1860.         cmp esp,cs:cp_validirqesp       ; source an IRQ or exception¿
  1861.         jne short cp_excdf0
  1862.         jmp cs:cp_int13vect
  1863. cp_excdf0:
  1864.         test byte ptr [esp+14],2        ; exception, from V86?
  1865.         jnz short cp_excdv86
  1866.         pushad                          ; nope, pmode exception
  1867.         mov al,0dh
  1868.         jmp cp_exc
  1869. ;-----------------------------------------------------------------------------
  1870. cp_excdv86:                             ; violation from V86 mode
  1871.         add esp,4
  1872.         pushad
  1873.         mov cx,18h
  1874.         mov ds,cx
  1875.         movzx ebx,word ptr [esp+36]
  1876.         shl ebx,4
  1877.         add ebx,[esp+32]
  1878.         inc word ptr [esp+32]
  1879.         mov al,[ebx]
  1880.         mov edx,3
  1881.         cmp al,0cch
  1882.         je short cp_v86int
  1883.         mov dl,4
  1884.         cmp al,0ceh
  1885.         je short cp_v86int
  1886.         inc word ptr [esp+32]
  1887.         mov dl,[ebx+1]
  1888.         cmp dl,32h
  1889.         je p_cpmode2
  1890.         cmp dl,0ffh
  1891.         je cp_int3_d
  1892. ;-----------------------------------------------------------------------------
  1893. cp_v86int:                              ; need to simulate a real mode int
  1894.         movzx ebx,word ptr [esp+48]
  1895.         shl ebx,4
  1896.         sub word ptr [esp+44],6
  1897.         add ebx,[esp+44]
  1898.         mov ax,[esp+40]
  1899.         mov [ebx+4],ax
  1900.         and ah,0fch
  1901.         mov [esp+41],ah
  1902.         mov ax,[esp+36]
  1903.         mov [ebx+2],ax
  1904.         mov ax,[esp+32]
  1905.         mov [ebx],ax
  1906.         mov eax,[edx*4]
  1907.         mov [esp+32],ax
  1908.         shr eax,16
  1909.         mov [esp+36],ax
  1910.         popad
  1911.         iretd
  1912. ;═════════════════════════════════════════════════════════════════════════════
  1913. ; all exceptions except 0dh. all are terminal, others are redirected.
  1914. cp_exc0:
  1915.         push eax
  1916.         mov ax,1000h
  1917.         jmp cp_irq
  1918. cp_exc1:
  1919.         push eax
  1920.         mov ax,1001h
  1921.         jmp cp_irq
  1922. cp_exc2:
  1923.         push eax
  1924.         mov ax,1002h
  1925.         jmp cp_irq
  1926. cp_exc3:
  1927.         pushad
  1928.         mov al,3
  1929.         jmp short cp_exc
  1930. cp_exc4:
  1931.         pushad
  1932.         mov al,4
  1933.         jmp short cp_exc
  1934. cp_exc5:
  1935.         push eax
  1936.         mov ax,1005h
  1937.         jmp cp_irq
  1938. cp_exc6:
  1939.         pushad
  1940.         mov al,6
  1941.         jmp short cp_exc
  1942. cp_exc7:
  1943.         push eax
  1944.         mov ax,1007h
  1945.         jmp cp_irq
  1946. cp_exc8:
  1947.         pushad
  1948.         mov al,8
  1949.         jmp short cp_exc
  1950. cp_exc9:
  1951.         pushad
  1952.         mov al,9
  1953.         jmp short cp_exc
  1954. cp_exca:
  1955.         pushad
  1956.         mov al,0ah
  1957.         jmp short cp_exc
  1958. cp_excb:
  1959.         pushad
  1960.         mov al,0bh
  1961.         jmp short cp_exc
  1962. cp_excc:
  1963.         pushad
  1964.         mov al,0ch
  1965.         jmp short cp_exc
  1966. cp_exce:
  1967.         pushad
  1968.         mov al,0eh
  1969.         jmp short cp_exc
  1970. cp_excf:
  1971.         pushad
  1972.         mov al,0ffh
  1973. ;-----------------------------------------------------------------------------
  1974. cp_exc:                                 ; main exception handler
  1975.         mov ax,10h
  1976.         mov ds,ax
  1977.         mov es,ax
  1978.         mov fs,ax
  1979.         mov gs,_selzero
  1980.         cld
  1981.         jmp _exit
  1982. ;═════════════════════════════════════════════════════════════════════════════
  1983. ; IRQ redirector between modes
  1984. cp_irq0:
  1985.         push eax
  1986.         mov ax,0008h
  1987.         jmp short cp_irq
  1988. cp_irq1:
  1989.         push eax
  1990.         mov ax,0109h
  1991.         jmp short cp_irq
  1992. cp_irq2:
  1993.         push eax
  1994.         mov ax,020ah
  1995.         jmp short cp_irq
  1996. cp_irq3:
  1997.         push eax
  1998.         mov ax,030bh
  1999.         jmp short cp_irq
  2000. cp_irq4:
  2001.         push eax
  2002.         mov ax,040ch
  2003.         jmp short cp_irq
  2004. cp_irq5:
  2005.         push eax
  2006.         mov ax,050dh
  2007.         jmp short cp_irq
  2008. cp_irq6:
  2009.         push eax
  2010.         mov ax,060eh
  2011.         jmp short cp_irq
  2012. cp_irq7:
  2013.         push eax
  2014.         mov ax,070fh
  2015.         jmp short cp_irq
  2016. cp_irq8:
  2017.         push eax
  2018.         mov ax,0870h
  2019.         jmp short cp_irq
  2020. cp_irq9:
  2021.         push eax
  2022.         mov ax,0971h
  2023.         jmp short cp_irq
  2024. cp_irqa:
  2025.         push eax
  2026.         mov ax,0a72h
  2027.         jmp short cp_irq
  2028. cp_irqb:
  2029.         push eax
  2030.         mov ax,0b73h
  2031.         jmp short cp_irq
  2032. cp_irqc:
  2033.         push eax
  2034.         mov ax,0c74h
  2035.         jmp short cp_irq
  2036. cp_irqd:
  2037.         push eax
  2038.         mov ax,0d75h
  2039.         jmp short cp_irq
  2040. cp_irqe:
  2041.         push eax
  2042.         mov ax,0e76h
  2043.         jmp short cp_irq
  2044. cp_irqf:
  2045.         push eax
  2046.         mov ax,0f77h
  2047. ;─────────────────────────────────────────────────────────────────────────────
  2048. cp_irq:                                 ; main IRQ handler thingy
  2049.         mov ss:cp_v86irqnum,al
  2050.         movzx eax,ah
  2051.         bt dword ptr ss:_irqmode,eax
  2052.         setc ss:cp_v86irqmode
  2053.         pop eax
  2054.         test byte ptr [esp+10],2
  2055.         jnz short cp_irqv86
  2056.         push ds es fs gs                ; real mode IRQ from pmode
  2057.         pushfd
  2058.         push cs
  2059.         push offset cp_irqpd
  2060.         pushad
  2061.         mov ax,10h
  2062.         mov ds,ax
  2063.         mov al,18h
  2064.         mov gs,ax
  2065.         mov al,cp_v86irqnum
  2066.         mov ebp,offset c_irqreal
  2067.         movzx ebx,cp_v86irqmode
  2068.         jmp cp_v86irqintr[ebx*4]
  2069. cp_irqpd:
  2070.         pop gs fs es ds
  2071.         iretd
  2072. ;─────────────────────────────────────────────────────────────────────────────
  2073. cp_irqv86:                              ; IRQ from V86, safe or norm redirect
  2074.         cmp cs:cp_v86irqmode,0
  2075.         jne short cp_irqv86s
  2076.         pushad                          ; normal IRQ redirection
  2077.         mov ax,18h
  2078.         mov ds,ax
  2079.         movzx edx,ss:cp_v86irqnum
  2080.         jmp cp_v86int
  2081. ;-----------------------------------------------------------------------------
  2082. cp_irqv86s:                             ; safe IRQ redirection
  2083.         pushfd
  2084.         push cs
  2085.         push offset cp_irqv86sd
  2086.         pushad
  2087.         mov ax,10h
  2088.         mov ds,ax
  2089.         mov al,18h
  2090.         mov gs,ax
  2091.         sub nextmodestack,STAKSAFE*16
  2092.         mov al,cp_v86irqnum
  2093.         mov ebp,offset c_irqreal
  2094.         jmp cp_v86irqintr[4]
  2095. ;-----------------------------------------------------------------------------
  2096. cp_irqv86sd:                            ; done with safe IRQ
  2097.         add nextmodestack,STAKSAFE*16
  2098.         iretd
  2099.  
  2100. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2101. ; Custom get IRQ handler offset
  2102. ; In:
  2103. ;   BL - IRQ num (0-0fh)
  2104. ; Out:
  2105. ;   EDX - offset of IRQ handler
  2106. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2107. cp_getirqvect:
  2108.         push ebx
  2109.         pushf
  2110.         cli
  2111.         movzx ebx,bl
  2112.         mov bl,intslottbl[ebx]
  2113.         cmp bl,13
  2114.         je short cp_getirqvectf0
  2115.         lea ebx,[ebx*8]
  2116.         add ebx,cp_idt32ptr
  2117.         mov dx,[ebx+6]
  2118.         shl edx,16
  2119.         mov dx,[ebx]
  2120. cp_getirqvectd:
  2121.         popf
  2122.         pop ebx
  2123.         ret
  2124. cp_getirqvectf0:
  2125.         mov edx,cp_int13vect
  2126.         jmp short cp_getirqvectd
  2127. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2128. ; Custom set IRQ handler offset
  2129. ; In:
  2130. ;   BL - IRQ num (0-0fh)
  2131. ;   EDX - offset of IRQ handler
  2132. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2133. cp_setirqvect:
  2134.         push ebx
  2135.         pushf
  2136.         cli
  2137.         movzx ebx,bl
  2138.         mov bl,intslottbl[ebx]
  2139.         cmp bl,13
  2140.         je short cp_setirqvectf0
  2141.         lea ebx,[ebx*8]
  2142.         add ebx,cp_idt32ptr
  2143.         mov [ebx],dx
  2144.         shr edx,16
  2145.         mov [ebx+6],dx
  2146. cp_setirqvectd:
  2147.         popf
  2148.         pop ebx
  2149.         ret
  2150. cp_setirqvectf0:
  2151.         mov cp_int13vect,edx
  2152.         jmp short cp_setirqvectd
  2153. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2154. ; Custom set the base addx for a selector
  2155. ; In:
  2156. ;   AX - selector
  2157. ;   EDX - linear base addx for selector
  2158. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2159. cp_setselector:
  2160. if SELECTORS ne 0
  2161.         push eax edx
  2162.         movzx eax,ax
  2163.         and edx,0ffffffh
  2164.         or edx,92000000h
  2165.         mov dword ptr gdt32[eax+2],edx
  2166.         mov dl,[esp+3]
  2167.         mov byte ptr gdt32[eax+7],dl
  2168.         pop edx eax
  2169. endif
  2170.         ret
  2171.  
  2172. code32  ends
  2173.  
  2174. ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  2175. ; End of program (must be at end of program or you will suffer)
  2176. ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  2177. codeend segment para stack use32 'stack'
  2178. db STAKLEN*16 dup(?)
  2179. codeend ends
  2180.         end     start16
  2181.  
  2182.